package com.neusoft.neuiotms.dcom.task;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;

import com.alibaba.fastjson.JSONObject;
import com.neusoft.bizcore.schedule.service.JobMgrService;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.neuiotms.dcom.constants.DCOMConstants;
import com.neusoft.neuiotms.dcom.model.DutyArrangementResult;
import com.neusoft.neuiotms.dcom.model.InspectionRule;
import com.neusoft.neuiotms.dcom.model.InspectionTask;
import com.neusoft.neuiotms.dcom.model.InspectionTaskProject;
import com.neusoft.neuiotms.dcom.model.InspectionTaskProjectItemValue;
import com.neusoft.neuiotms.dcom.model.TeamUser;
import com.neusoft.neuiotms.dcom.model.enums.InspectionRuleStatus;
import com.neusoft.neuiotms.dcom.repository.DutyArrangementResultRepository;
import com.neusoft.neuiotms.dcom.repository.InspectionRuleRepository;
import com.neusoft.neuiotms.dcom.repository.InspectionTaskRepository;
import com.neusoft.neuiotms.dcom.util.SendingMessageDcom;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class InspectionTaskJob extends QuartzJobBean {
    @Autowired
    private InspectionRuleRepository ruleRepository;

    @Autowired
    private InspectionTaskRepository taskRepository;

    @Autowired
    private DutyArrangementResultRepository dutyArrangementResultRepository;

    @Autowired
    private JobMgrService jobMgrService;

    @Autowired
    private SendingMessageDcom sendingMessage;

    @Override
    protected void executeInternal(final JobExecutionContext context) throws JobExecutionException {
        InspectionTaskJob.log.info("巡检规则---定时--生成巡检任务----开始");
        //任务开始执行时间
        final LocalDateTime startTaskTime = LocalDateTime.now().withSecond(0).withNano(0);
        InspectionTaskJob.log.info("startTaskTime: " + startTaskTime);
        //规则Id
        final Long inspecitonRuleId = context.getJobDetail().getJobDataMap().getLong("inspectionRuleId");
        //规则
        try {
            final InspectionRule rule = this.ruleRepository.findById(inspecitonRuleId).get();
            //在时间范围内的
            if ((this.localDateTime2Date(startTaskTime).getTime() >= rule.getStartDateTime().getTime())
                    && (this.localDateTime2Date(startTaskTime).getTime() <= rule.getEndDateTime().getTime())) {
                final LocalDateTime endTaskTime = startTaskTime.plusHours(rule.getDuration());
                InspectionTaskJob.log.info("endTaskTime: " + endTaskTime);

                if ((rule.getInspectionProject() != null) && !rule.getInspectionProject().isEmpty()) {
                    final InspectionTask task = new InspectionTask();
                    task.setName(rule.getName() + "-" + startTaskTime);
                    task.setInspectionRule(rule);
                    task.setStartTaskTime(this.localDateTime2Date(startTaskTime));
                    task.setEndTaskTime(this.localDateTime2Date(endTaskTime));
                    final List<InspectionTaskProject> taskProjectLists = new ArrayList<>();
                    rule.getInspectionProject().forEach(project -> {
                        if ((project.getProjectConcrete() != null) && !project.getProjectConcrete().isEmpty()
                                && (project.getInspectionItem() != null) && !project.getInspectionItem().isEmpty()) {
                            project.getProjectConcrete().forEach(concrete -> {
                                final InspectionTaskProject taskProject = new InspectionTaskProject();
                                taskProject.setConcreteCode(concrete.getConcreteCode());
                                taskProject.setConcreteName(concrete.getConcreteName());
                                taskProject.setInspectionTask(task);
                                taskProject.setLocationCode(project.getLocationCode());
                                taskProject.setLocationName(project.getLocationName());
                                final List<InspectionTaskProjectItemValue> itemValues =
                                        new ArrayList<>();
                                project.getInspectionItem().forEach(t -> {
                                    final InspectionTaskProjectItemValue itemValue =
                                            new InspectionTaskProjectItemValue();
                                    itemValue.setRuleProjectItem(t);
                                    itemValue.setInspectionTaskProject(taskProject);
                                    itemValues.add(itemValue);
                                });
                                taskProject.setItemValue(itemValues);
                                taskProjectLists.add(taskProject);
                            });
                        }
                    });
                    task.setInspectionTaskProject(taskProjectLists);
                    this.taskRepository.save(task);

                    InspectionTaskJob.log.info("巡检规则---定时--生成巡检任务----查询当前部门：" + rule.getOrgName() + " 当前职能："
                            + rule.getInspectionType() + " 的在班人员");
                    final Searchable searchable = new Searchable();
                    searchable.put("orgCode", rule.getOrgCode());
                    searchable.put("functionalGroupId", rule.getInspectionType());
                    searchable.put("afterStartTime", this.localDateTime2Date(startTaskTime).getTime());
                    searchable.put("beforeEndTime", this.localDateTime2Date(startTaskTime).getTime());
                    final List<DutyArrangementResult> list = this.dutyArrangementResultRepository.index(searchable);
                    InspectionTaskJob.log.info("巡检规则---定时--生成巡检任务----查询在班人员结束");

                    final List<String> users = new ArrayList<>();
                    list.forEach(duty -> {
                        users.addAll(duty.getTeamGroup().getUsers().stream().map(TeamUser::getCode)
                                .collect(Collectors.toList()));
                    });
                    if (!users.isEmpty()) {
                        InspectionTaskJob.log.info("巡检规则---定时--生成巡检任务----开始---在班人员发送通知");
                        final JSONObject obj = new JSONObject();
                        final String[] type = {DCOMConstants.INFORM_TYPE_NOTICE, DCOMConstants.INFORM_TYPE_MAIL };
                        obj.put("title", "巡检任务");
                        obj.put("type", type);
                        obj.put("appCode", "dcom");

                        final JSONObject sys = new JSONObject();
                        sys.put("content", "您有开始于 " + startTaskTime + "的巡检任务");
                        sys.put("noticeType", "巡检任务");
                        sys.put("noticeRoute", "dcom_inspectionTask");

                        final JSONObject info = new JSONObject();
                        info.put("s_id", task.getId());
                        sys.put("businessInfo", info.toString());
                        sys.put("users", users);

                        obj.put("system", sys);
                        //        System.out.println(sys);
                        this.sendingMessage.SendMsgToNotice(obj.toString());
                        InspectionTaskJob.log.info("巡检规则---定时--生成巡检任务----开始---在班人员发送通知");
                    }
                    InspectionTaskJob.log.info("巡检规则---定时--生成巡检任务----结束---在班人员发送通知");
                }

            } else {
                this.jobMgrService.pauseJob(rule.getCode());
                this.jobMgrService.deleteJob(rule.getCode());
                rule.setStatus(InspectionRuleStatus.stop);
                this.ruleRepository.save(rule);
            }
        } catch (final Exception e) {
            InspectionTaskJob.log.error(e.getMessage(), e);
        }

        InspectionTaskJob.log.info("巡检规则---定时--生成巡检任务----结束");
    }

    private Date localDateTime2Date(final LocalDateTime localDateTime) {
        final ZoneId zoneId = ZoneId.systemDefault();
        final ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

}
